<template>
  <view class="sv-exam" :style="'--card-header-height:' + cardHeaderHeight">
    <template v-if="showExam">
      <!-- 答题区域 -->
      <!-- #ifdef VUE2 -->
      <exam-paper :paper.sync="curPaper"></exam-paper>
      <exam-card v-if="showCard" :paper.sync="curPaper"></exam-card>
      <!-- #endif -->
      <!-- #ifdef VUE3 -->
      <exam-paper v-model:paper="curPaper"></exam-paper>
      <exam-card v-if="showCard" v-model:paper="curPaper"></exam-card>
      <!-- #endif -->
      <!-- 答题卡区域 -->
    </template>
    <view class="exam-empty-loading" v-else>
      <view class="exam-loading-cube"></view>
      <view class="exam-loading-text">加载中...</view>
    </view>
    <!-- 退出拦截 - 背题模式不做拦截 -->
    <sv-intercept-back v-if="type !== config.examTypeDict[0]"></sv-intercept-back>
  </view>
</template>

<script>
import ExamCard from './exam-card.vue'
import ExamPaper from './exam-paper.vue'
import config from '@/uni_modules/sv-exam-plus/config.js'
import { copyright } from '@/uni_modules/sv-exam-plus/utils/index.js'
import store from '@/uni_modules/sv-exam-plus/store/index.js'

export default {
  components: {
    ExamCard,
    ExamPaper
  },
  props: {
    /**
     * 三种答题模式
     * recite 背题模式 题库中顺序出题，带有答案，只需看题背答案，无需手动写题，可继续背题
     * practice 刷题模式 题库中顺序出题，答题完自动批改对错并给出答案，可继续或重新答题
     * exam 模拟考试 题库中随机抽取指定数量道题并打乱顺序，提交后自动批改，退出考试时弹出提示，时间到自动交卷
     */
    type: {
      type: String,
      default: ''
    },
    lib: {
      type: String,
      default: ''
    },
    data: {
      type: Array,
      default: () => []
    },
    favs: {
      type: Array,
      default: () => []
    },
    // 是否显示答题卡
    showCard: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      config, // 兼容写法，需要先声明否则报错
      cardHeaderHeight: '50px', // 根据是否显示答题卡，动态改变试题内容盒子高度
      curPaper: {}, // 初始默认题目
      showExam: false // 题目是否加载完成
    }
  },
  computed: {
    examData: {
      set(newData) {
        store.commit('updateData', newData)
      },
      get() {
        return store.state.examData
      }
    },
    examType: {
      set(newType) {
        store.commit('updateType', newType)
      },
      get() {
        return store.state.examType
      }
    },
    examFavs: {
      set(newFavs) {
        store.commit('updateFavs', newFavs)
      },
      get() {
        return store.state.examFavs
      }
    },
    examIndex: {
      set(newIndex) {
        store.commit('updateIndex', newIndex)
      },
      get() {
        return store.state.examIndex
      }
    }
  },
  watch: {
    // 监听考试类型改变
    'type': {
      handler(newType) {
        store.commit('updateType', newType)
        store.commit('updateIndex', this.getIndex())
        this.curPaper.index = this.examIndex
        // this.curPaper = { data: this.examData[this.examIndex], index: this.examIndex }
        const storage = uni.getStorageSync('sv-exam')
        uni.setStorageSync('sv-exam', Object.assign({ ...storage }, { examType: newType }))
      },
      immediate: true
    },
    // 监听题目加载完成
    'data': {
      handler(newData) {
        store.commit('updateData', newData)
        store.commit('updateNum')
        this.curPaper.data = this.examData[this.examIndex]
        if (newData.length > 0) this.showExam = true
      },
      immediate: true
    },
    // 监听收藏
    'favs': {
      handler(newFavs) {
        store.commit('updateFavs', newFavs)
      }
    },
    'curPaper.index': {
      handler(newIndex) {
        this.setIndex(newIndex)
        this.$emit('changePaper', this.curPaper)
      }
    }
  },
  created() {
    this.init()
    copyright()
  },
  // #ifdef VUE2
  beforeDestroy() {
    this.$emit('quit', this.examData)
  },
  // #endif
  // #ifdef VUE3
  beforeUnmount() {
    this.$emit('quit', this.examData)
  },
  // #endif
  methods: {
    // 初始化
    init() {
      this.cardHeaderHeight = this.showCard ? '50px' : '0px'
      store.commit('updateType', this.type)
      store.commit('updateData', this.data)
      store.commit('updateFavs', this.favs)
      store.commit('updateIndex', this.getIndex())
      store.commit('updateNum')
      this.curPaper = { data: this.examData[this.examIndex], index: this.examIndex }
    },
    setIndex(newIndex) {
      if (!this.lib) return
      const storage = uni.getStorageSync('sv-exam')
      switch (this.type) {
        case this.config.examTypeDict[0]:
          storage[this.lib] = Object.assign({ ...storage[this.lib] }, { reciteIndex: newIndex })
          break
        case this.config.examTypeDict[1]:
          storage[this.lib] = Object.assign({ ...storage[this.lib] }, { practiceIndex: newIndex })
          break
      }
      uni.setStorageSync('sv-exam', storage)
    },
    getIndex() {
      let index = 0
      const storage = uni.getStorageSync('sv-exam')
      try {
        if (!this.lib) throw new Error('lib is undefined')
        if (!this.type) throw new Error('type is undefined')
        switch (this.type) {
          case config.examTypeDict[0]:
            index = storage[this.lib].reciteIndex || 0
            break
          case config.examTypeDict[1]:
            index = storage[this.lib].practiceIndex || 0
            break
          case config.examTypeDict[2]:
            index = 0
            break
        }
      } catch (e) {
        // 当缓存中缺失部分参数时，默认归零
        index = 0
      }
      return index
    }
  }
}
</script>

<style lang="scss">
.sv-exam {
  --bg-color: #ffffff; // 主要背景
  --sub-bg-color: rgba(0, 216, 134, 0.1); // 次要背景
  --border-color: #e6e6e6; // 边框色
  --border-highlight-color: #01beff; // 边框高亮色
  --primary-color: #01beff; // 行为配色
  --success-color: #00d886; // 行为配色
  --warning-color: #ff0808; // 行为配色
  --error-color: #ff444f; // 行为配色
  --info-color: rgba(0, 216, 134, 0.1); // 行为配色
  --card-height: 50vh; // 答题卡高度

  // --card-header-height: #{v-bind(cardHeaderHeight)}; // 答题卡头部高度
  // 单元单位建议非必要勿修改，使用rpx会存在一些样式问题，这里统一使用px
  // --paper-unit-12: 24rpx; // 单元尺寸 12px
  // --paper-unit-16: 32rpx; // 单元尺寸 16px
  --paper-unit-12: 12px; // 单元尺寸 12px
  --paper-unit-16: 16px; // 单元尺寸 16px

  width: 100%;
  height: 100%;
  box-sizing: border-box;
  font-size: 14px;

  .exam-empty-loading {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;

    .exam-loading-text {
      font-size: var(--paper-unit-12);
      line-height: 2.4;
    }
  }
}

.primary-color {
  color: var(--primary-color);
}

.success-color {
  color: var(--success-color);
}

.warning-color {
  color: var(--warning-color);
}

.error-color {
  color: var(--error-color);
}

.info-color {
  color: var(--info-color);
}

// loading动画
.exam-loading-cube {
  --size: 10px;
  --color: white;
  width: 20px;
  height: 20px;
  position: relative;
}

.exam-loading-cube::after,
.exam-loading-cube::before {
  box-sizing: border-box;
  position: absolute;
  content: '';
  width: var(--size);
  height: var(--size);
  top: 50%;
  animation: exam-loading-cube-up 2.4s cubic-bezier(0, 0, 0.24, 1.21) infinite;
  left: 50%;
  background: var(--color);
  box-shadow: 0 0 calc(var(--size) / 3) rgba(0, 0, 0, 0.25);
}

.exam-loading-cube::after {
  background: var(--color);
  top: calc(50% - var(--size));
  left: calc(50% - var(--size));
  animation: exam-loading-cube-down 2.4s cubic-bezier(0, 0, 0.24, 1.21) infinite;
}

@keyframes exam-loading-cube-down {
  0%,
  100% {
    transform: none;
  }

  25% {
    transform: translateX(100%);
  }

  50% {
    transform: translateX(100%) translateY(100%);
  }

  75% {
    transform: translateY(100%);
  }
}

@keyframes exam-loading-cube-up {
  0%,
  100% {
    transform: none;
  }

  25% {
    transform: translateX(-100%);
  }

  50% {
    transform: translateX(-100%) translateY(-100%);
  }

  75% {
    transform: translateY(-100%);
  }
}
</style>
